package com.maslyk.invitation.entitybean;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.maslyk.configuration.ConfigurationManager;
import com.maslyk.invitation.audit.ObjectName;
import com.maslyk.invitation.audit.PropertyLabel;
import com.maslyk.invitation.entitybean.abstrct.GenericEntity;
import com.maslyk.invitation.enums.OrderPositionTypeEnum;

/**
 *
 * @author kris
 */
@Entity
@Table(name = "invitation")
@ObjectName(label="Zaproszenie")
public class Invitation extends GenericEntity implements IOrderPosition
{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "code")
    @PropertyLabel(label="Kod")
    private String code;
    @Column(name = "bridename")
    @PropertyLabel(label="Panna młoda")
    private String bridename;
    @Column(name = "bridegroom")
    @PropertyLabel(label="Pan młody")
    private String bridegroom;
    @Column(name = "weddingdatetime")
    @Temporal(TemporalType.TIMESTAMP)
    @PropertyLabel(label="Data ślubu")
    private Date weddingDateTime;
    @Column(name = "weddingplace")
    @PropertyLabel(label="Miesce ślubu")
    private String weddingplace;
    @Column(name = "weddingpartyplace")
    @PropertyLabel(label="Miejsce przyjęcia weselnego")
    private String weddingpartyplace;
    @Column(name = "totalCount")
    @PropertyLabel(label="Całkowita ilość")
    private Integer totalCount = 0;
    @Column(name = "overPrintCount")
    @PropertyLabel(label="Ilość z nadrukiem")
    private Integer overPrintCount = 0;
    @Column(name = "personalizecount")
    @PropertyLabel(label="Ilość z personalizacją")
    private Integer personalizecount = 0;
    @Column(name = "envelopepersonalizecount")
    @PropertyLabel(label="Ilość personalizowanych kopert")
    private Integer envelopepersonalizecount = 0;
    @Column(name = "unitprice")
    @PropertyLabel(label="Cena zaproszenia")
    private BigDecimal unitprice = new BigDecimal(0.00);
    @Column(name = "paperChanged", nullable=true)
    @PropertyLabel(label="Zmiana papieru")
    private Boolean paperChanged = false;
    @Column(name = "cuttingNames", nullable=true)
    @PropertyLabel(label="Wycinanie imion")
    private Boolean cuttingNames = false;
    @Column(name = "assembling", nullable=true)
    @PropertyLabel(label="Składanie")
    private Boolean assembling = true;
    @Column(name = "fontType")
    @PropertyLabel(label="Typ czcionki")
    private String fontType;
    @Column(name = "fontColor")
    @PropertyLabel(label="Kolor czcionki")
    private int fontColor = 0;
    @Column(name = "coverColor")
    @PropertyLabel(label="Kolor okładki")
    private int coverColor = 0;
    @Column(name = "note")
    @PropertyLabel(label="Uwagi")
    private String note;
    @JoinColumn(name = "orderID", referencedColumnName = "id")
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private Order orderID;
    @ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "invitationtotext",joinColumns = @JoinColumn(name="invitationid"),
        inverseJoinColumns = @JoinColumn(name="textid"))
    private List<Text> textList = new ArrayList<Text>();
    
	//bi-directional many-to-one association to FeeInvitation
	@OneToMany(mappedBy="invitation", cascade=CascadeType.ALL)
	private List<FeeInvitation> feeInvitations = new ArrayList<FeeInvitation>(); 

    @Transient
    private StringBuffer calculatingNote = new StringBuffer();

    public Invitation()
    {
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getCode()
    {
        return code;
    }

    public void setCode(String code)
    {
        this.code = code;
    }

    public String getBridename()
    {
        return bridename;
    }

    public void setBridename(String bridename)
    {
        this.bridename = bridename;
    }

    public String getBridegroom()
    {
        return bridegroom;
    }

    public void setBridegroom(String bridegroom)
    {
        this.bridegroom = bridegroom;
    }

    public Date getWeddingDateTime()
    {
        return weddingDateTime;
    }

    public void setWeddingDateTime(Date weddingDateTime)
    {
        this.weddingDateTime = weddingDateTime;
    }

    public String getWeddingplace()
    {
        return weddingplace;
    }

    public void setWeddingplace(String weddingplace)
    {
        this.weddingplace = weddingplace;
    }

    public String getWeddingpartyplace()
    {
        return weddingpartyplace;
    }

    public void setWeddingpartyplace(String weddingpartyplace)
    {
        this.weddingpartyplace = weddingpartyplace;
    }

    public Integer getTotalCount()
    {
        return totalCount;
    }

    public void setTotalCount(Integer totalCount)
    {
        this.totalCount = totalCount;
    }

    public Integer getPersonalizecount()
    {
        return personalizecount;
    }

    public void setPersonalizecount(Integer personalizecount)
    {
        this.personalizecount = personalizecount;
    }

    public BigDecimal getUnitprice()
    {
        return unitprice;
    }

    public void setUnitprice(BigDecimal unitprice)
    {
        this.unitprice = unitprice;
    }

    public String getFontType()
    {
        return fontType;
    }

    public void setFontType(String fontType)
    {
        this.fontType = fontType;
    }

    public int getFontColor()
    {
        return fontColor;
    }

    public void setFontColor(int fontColor)
    {
        this.fontColor = fontColor;
    }

    public String getNote()
    {
        return note;
    }

    public void setNote(String note)
    {
        this.note = note;
    }

    public Order getOrderID()
    {
        return orderID;
    }

    public void setOrderID(Order orderID)
    {
        this.orderID = orderID;
    }

    public Boolean getAssembling()
    {
        return assembling;
    }

    public void setAssembling(Boolean assembly)
    {
        this.assembling = assembly;
    }

    public Integer getEnvelopepersonalizecount()
    {
        return envelopepersonalizecount;
    }

    public void setEnvelopepersonalizecount(Integer envelopepersonalizecount)
    {
        this.envelopepersonalizecount = envelopepersonalizecount;
    }

    public Boolean getPaperChanged()
    {
        return paperChanged;
    }

    public void setPaperChanged(Boolean paperChanged)
    {
        this.paperChanged = paperChanged;
    }

    public Boolean getCuttingNames()
    {
        return cuttingNames;
    }

    public void setCuttingNames(Boolean cuttingNames)
    {
        this.cuttingNames = cuttingNames;
    }

    public Integer getOverPrintCount()
    {
        return overPrintCount;
    }

    public void setOverPrintCount(Integer overPrintCount)
    {
        this.overPrintCount = overPrintCount;
    }

    public int getCoverColor()
    {
        return coverColor;
    }

    public void setCoverColor(int coverColor)
    {
        this.coverColor = coverColor;
    }

    public List<Text> getTextList()
    {
        return textList;
    }

    public void setTextList(List<Text> textList)
    {
        this.textList = textList;
    }
    
    public List<FeeInvitation> getFeeInvitations()
	{
		return feeInvitations;
	}

	public void setFeeInvitations(List<FeeInvitation> feeinvitations)
	{
		this.feeInvitations = feeinvitations;
	}

	@Override
    public int hashCode()
    {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object)
    {
        return super.equals(object);
    }

    @Override
    public String toString()
    {
        return super.toString();
    }

    public BigDecimal getAmount()
    {
        calculatingNote = new StringBuffer();
        // kwota podstawowa od wszystkich zaproszen
        double baseSum = totalCount * unitprice.doubleValue();
        
        if(baseSum > 0.00)
        	calculatingNote.append("kwota za zaproszenia: "+totalCount+" * "+unitprice.doubleValue()+" = "+baseSum+"<br>");

        double personalizationSum = 0.0;
        if(personalizecount > 0)
        {
            // koszt personalizacji zaproszen
            personalizationSum = personalizecount * ConfigurationManager.getInstance().getITEM_PERSONALIZE_PRICE().doubleValue();
            calculatingNote.append("personalizacja zaproszen: " +personalizecount+" * "+ConfigurationManager.getInstance().getITEM_PERSONALIZE_PRICE().doubleValue() +" = "+personalizationSum+"<br>");
        }

        double envelopesPersonalization = 0.0;
        if(envelopepersonalizecount > 0)
        {
            // koszt personalizacji kopert
            envelopesPersonalization = envelopepersonalizecount * ConfigurationManager.getInstance().getITEM_ENVELOPE_PERSONALIZE_PRICE().doubleValue();
            calculatingNote.append("personalizacja kopert: " +envelopepersonalizecount+" * "+ConfigurationManager.getInstance().getITEM_ENVELOPE_PERSONALIZE_PRICE().doubleValue() +" = "+envelopesPersonalization+"<br>");
        }

        // koszt wyciecia imion na zaproszeniu
        double cuteNamesSum = 0.0;
        if(cuttingNames)
        {
            cuteNamesSum = totalCount * ConfigurationManager.getInstance().getCUTTING_NAMES();
            calculatingNote.append("wypalanie imion na zaproszeniach: " +totalCount+" * "+ConfigurationManager.getInstance().getCUTTING_NAMES()+" = "+cuteNamesSum+"<br>");
        }

        // koszt zlozenia zaproszen
        double assemblyCost = 0.0;
        if(assembling)
        {
            assemblyCost = totalCount * 0.50;
            
            if(assemblyCost > 0.00)
            	calculatingNote.append("skladanie: " +totalCount+" * 0.50 = "+assemblyCost+"<br>");
        }
        
        double textAssembly = 0.00;
        
        if(overPrintCount > 1 && overPrintCount <= 50)
        	textAssembly = 30.00;
        
        if(textAssembly > 0.0)
            calculatingNote.append("sklad tekstu = "+textAssembly+"<br>");

        double fees = 0.00;
        for(FeeInvitation feeObj : feeInvitations)
        {
        	double fee = feeObj.getAmount();
        	fees += fee;
        	calculatingNote.append(feeObj.getPriceParameter().getName()+ " = "+ fee+"<br>");
        }

        double totalAmount = 	baseSum + 
        						personalizationSum +
        						envelopesPersonalization +
        						cuteNamesSum +
        						assemblyCost +
        						textAssembly +
        						fees;
        
        BigDecimal amount = new BigDecimal(totalAmount);
        amount.setScale(2,BigDecimal.ROUND_HALF_UP);
        return amount;
    }

    public OrderPositionTypeEnum getType()
    {
        return OrderPositionTypeEnum.INVITATION;
    }

    public String getCalculatingNote()
    {
        return calculatingNote.toString();
    }
    
	public static String getBeanName()
	{
		return "invitationBean";
	}

	public String getKey() {
		return getOrderID().getNumber();
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Invitation inv = (Invitation) super.clone();
		inv.setId(null);
		inv.setOrderID(null);
		
		List<FeeInvitation> invitations = new ArrayList<FeeInvitation>();
		
		for(FeeInvitation fi : feeInvitations)
			invitations.add((FeeInvitation) fi.clone());
		inv.setFeeInvitations(invitations);
		
		return inv;
	}
}
